import * as fs from 'fs';
import * as path from 'path';

/**
 * OpenHarmony 架构推理引擎
 * 
 * 功能：
 * 1. 基于学习的架构信息智能推断 external_deps
 * 2. 智能推断 include_dirs
 * 3. 智能推断 module_out_path
 * 4. 智能推断测试目录结构
 * 
 * 特点：
 * - 本地学习模式：使用完整的 openharmony-architecture.json (3.29 MB)
 * - 打包模式：优雅降级，使用内置规则
 */
export class OpenHarmonyInferenceEngine {
    private architecture: {
        components: Array<{
            name: string;
            subsystem: string;
            innerKits: any[];
        }>;
        headerToComponent: { [header: string]: string };
        dependencies: { [component: string]: string[] };
        innerkits: Array<{
            component: string;
            headers: string[];
        }>;
    } | null = null;

    private builtInRules: {
        headerToExternalDeps: { [header: string]: string };
        commonDeps: { [type: string]: string[] };
    } = {
        // 内置的高频头文件 → external_deps 映射（轻量级，打包用）
        headerToExternalDeps: {
            'ipc_skeleton.h': 'ipc',
            'iremote_broker.h': 'ipc',
            'iremote_object.h': 'ipc',
            'iremote_stub.h': 'ipc',
            'iremote_proxy.h': 'ipc',
            'message_parcel.h': 'ipc',
            'message_option.h': 'ipc',
            
            'hilog/log.h': 'hilog',
            'hilog_base/log_base.h': 'hilog',
            
            'samgr.h': 'samgr',
            'system_ability_definition.h': 'samgr',
            'if_system_ability_manager.h': 'samgr',
            
            'access_token.h': 'access_token',
            'accesstoken_kit.h': 'access_token',
            'nativetoken_kit.h': 'access_token',
            
            'bundle_mgr_interface.h': 'bundle_framework',
            'bundle_mgr_proxy.h': 'bundle_framework',
            
            'event_handler.h': 'eventhandler',
            'event_runner.h': 'eventhandler',
            
            'c_utils/common_timer_errors.h': 'c_utils',
            'c_utils/refbase.h': 'c_utils',
            
            // NDK 接口相关
            'OH_NativeImage.h': 'graphic_2d',
            'OH_PixelMap.h': 'image_framework',
            'OH_AVCodec.h': 'av_codec',
        },
        
        // 常见依赖组合
        commonDeps: {
            'service': ['ipc', 'hilog', 'samgr', 'c_utils'],
            'client': ['ipc', 'hilog', 'c_utils'],
            'ndk': ['hilog'],
        }
    };

    constructor() {
        this.loadArchitecture();
    }

    /**
     * 加载架构信息（如果存在）
     */
    private loadArchitecture(): void {
        try {
            const archPath = path.join(__dirname, '../knowledge/openharmony-architecture.json');
            if (fs.existsSync(archPath)) {
                const content = fs.readFileSync(archPath, 'utf-8');
                this.architecture = JSON.parse(content);
                console.log(`[InferenceEngine] ✅ 已加载完整架构信息（${Object.keys(this.architecture?.headerToComponent || {}).length} 个头文件映射）`);
            } else {
                console.log('[InferenceEngine] ⚠️ 未找到完整架构文件，使用内置规则');
            }
        } catch (e) {
            console.log('[InferenceEngine] ⚠️ 加载架构信息失败，使用内置规则:', e);
        }
    }

    /**
     * 推断 external_deps（基于 include 的头文件）
     * 
     * @param includes - 代码中包含的头文件列表
     * @returns 推断的 external_deps 数组
     */
    inferExternalDeps(includes: string[]): string[] {
        const depsSet = new Set<string>();

        for (const include of includes) {
            const headerName = path.basename(include);
            
            // 策略1：使用完整架构信息（如果已加载）
            if (this.architecture?.headerToComponent) {
                const component = this.architecture.headerToComponent[headerName];
                if (component) {
                    depsSet.add(component);
                    continue;
                }
            }

            // 策略2：使用内置规则
            const dep = this.builtInRules.headerToExternalDeps[headerName];
            if (dep) {
                depsSet.add(dep);
                continue;
            }

            // 策略3：基于路径推断
            // 例如: "ipc/ipc_skeleton.h" → "ipc"
            const pathParts = include.split('/');
            if (pathParts.length >= 2) {
                const possibleComponent = pathParts[0];
                // 常见的部件名
                const commonComponents = [
                    'ipc', 'hilog', 'samgr', 'access_token', 'bundle_framework',
                    'eventhandler', 'c_utils', 'graphic_2d', 'image_framework',
                    'audio_framework', 'camera_framework', 'av_codec', 'netstack'
                ];
                if (commonComponents.includes(possibleComponent)) {
                    depsSet.add(possibleComponent);
                }
            }
        }

        return Array.from(depsSet);
    }

    /**
     * 推断部件名（基于函数名）
     * 
     * @param functionName - 函数名（例如 "OH_NativeImage_Create"）
     * @returns 部件名或 null
     */
    inferComponentByFunction(functionName: string): string | null {
        // NDK 接口推断
        if (functionName.startsWith('OH_')) {
            const mapping: { [prefix: string]: string } = {
                'OH_NativeImage': 'graphic_2d',
                'OH_PixelMap': 'image_framework',
                'OH_AVCodec': 'av_codec',
                'OH_AudioStream': 'audio_framework',
                'OH_Camera': 'camera_framework',
                'OH_NativeBuffer': 'graphic_2d',
                'OH_Drawing': 'graphic_2d',
            };

            for (const [prefix, component] of Object.entries(mapping)) {
                if (functionName.startsWith(prefix)) {
                    return component;
                }
            }
        }

        return null;
    }

    /**
     * 查找 innerkit 头文件路径
     * 
     * @param componentName - 部件名
     * @returns 头文件路径数组
     */
    findInnerkitHeaders(componentName: string): string[] {
        if (!this.architecture?.innerkits) {
            return [];
        }

        const innerkit = this.architecture.innerkits.find(
            ik => ik.component === componentName
        );

        return innerkit?.headers || [];
    }

    /**
     * 推断测试目录结构
     * 
     * @param projectName - 项目名称
     * @param sourceFilePath - 源文件路径
     * @returns 推荐的测试目录结构
     */
    inferTestStructure(projectName: string, sourceFilePath: string): {
        recommended: 'test/unittest' | 'test/unittest/{module}';
        moduleName?: string;
    } {
        // 分析源文件路径，判断是否在子模块中
        const pathParts = sourceFilePath.split(/[/\\]/);
        
        // 查找 services, interfaces, frameworks 等关键目录
        const keyDirs = ['services', 'interfaces', 'frameworks', 'core'];
        let moduleName: string | undefined;

        for (let i = 0; i < pathParts.length; i++) {
            if (keyDirs.includes(pathParts[i]) && i + 1 < pathParts.length) {
                moduleName = pathParts[i + 1];
                break;
            }
        }

        if (moduleName) {
            return {
                recommended: 'test/unittest/{module}',
                moduleName
            };
        }

        return {
            recommended: 'test/unittest'
        };
    }

    /**
     * 智能生成 GN 配置
     * 
     * @param sourceFile - 源文件路径
     * @param includes - 包含的头文件
     * @returns 推荐的 GN 配置
     */
    generateSmartGNConfig(sourceFile: string, includes: string[]): {
        deps: string[];
        external_deps: string[];
        include_dirs: string[];
        module_out_path?: string;
    } {
        // 推断 external_deps
        const external_deps = this.inferExternalDeps(includes);

        // 推断常见 deps（本地依赖）
        const deps: string[] = [];

        // 推断 include_dirs
        const include_dirs: string[] = [
            '//foundation/communication/ipc/interfaces/innerkits/ipc_core/include',
            // 根据实际项目结构添加
        ];

        // 推断 module_out_path
        const pathParts = sourceFile.split(/[/\\]/);
        let subsystem = 'unknown';
        let module = 'unknown';

        // 尝试从路径提取子系统和模块
        for (let i = 0; i < pathParts.length; i++) {
            if (pathParts[i] === 'foundation' || pathParts[i] === 'base' || pathParts[i] === 'drivers') {
                if (i + 1 < pathParts.length) {
                    const fullModule = pathParts[i + 1];
                    // 例如: "communication_ipc" → subsystem="communication", module="ipc"
                    const parts = fullModule.split('_');
                    if (parts.length >= 2) {
                        subsystem = parts[0];
                        module = parts.slice(1).join('_');
                    } else {
                        subsystem = fullModule;
                        module = fullModule;
                    }
                }
                break;
            }
        }

        return {
            deps,
            external_deps,
            include_dirs,
            module_out_path: `${subsystem}/${module}`
        };
    }

    /**
     * 推断 Fuzz 配置路径
     * 
     * @param projectRoot - 项目根目录
     * @param fuzzerName - Fuzzer 名称
     * @returns fuzz_config_file 路径
     */
    inferFuzzConfigFile(projectRoot: string, fuzzerName: string): string {
        // 通常是相对于项目根的路径
        const pathParts = projectRoot.split(/[/\\]/);
        
        // 查找关键目录
        let relativePath = '';
        for (let i = pathParts.length - 1; i >= 0; i--) {
            if (['services', 'interfaces', 'frameworks'].includes(pathParts[i])) {
                relativePath = pathParts.slice(i).join('/');
                break;
            }
        }

        if (relativePath) {
            return `\${services_path}/${relativePath}/test/fuzztest/${fuzzerName}`;
        }

        return `test/fuzztest/${fuzzerName}`;
    }

    /**
     * 分析代码文件，提取关键信息
     * 
     * @param sourceCode - 源代码内容
     * @returns 提取的信息
     */
    analyzeSourceCode(sourceCode: string): {
        includes: string[];
        ndkInterfaces: string[];
        hasService: boolean;
        hasClient: boolean;
    } {
        const includes: string[] = [];
        const ndkInterfaces: string[] = [];

        // 提取 include
        const includeRegex = /#include\s+["<]([^">]+)[">]/g;
        let match;
        while ((match = includeRegex.exec(sourceCode)) !== null) {
            includes.push(match[1]);
        }

        // 提取 NDK 接口
        const ndkRegex = /\b(OH_\w+)\s*\(/g;
        while ((match = ndkRegex.exec(sourceCode)) !== null) {
            ndkInterfaces.push(match[1]);
        }

        // 判断是否是 Service 或 Client
        const hasService = /class\s+\w+\s*:\s*public\s+.*Stub/.test(sourceCode) ||
                          /REGISTER_SYSTEM_ABILITY/.test(sourceCode);
        const hasClient = /class\s+\w+\s*:\s*public\s+.*Proxy/.test(sourceCode);

        return {
            includes,
            ndkInterfaces,
            hasService,
            hasClient
        };
    }

    /**
     * 获取推荐的依赖（基于代码类型）
     * 
     * @param codeType - 代码类型 ('service' | 'client' | 'ndk' | 'default')
     * @returns 推荐的基础依赖
     */
    getRecommendedDeps(codeType: 'service' | 'client' | 'ndk' | 'default'): string[] {
        return this.builtInRules.commonDeps[codeType] || [];
    }
}

// 单例模式
let engineInstance: OpenHarmonyInferenceEngine | null = null;

export function getInferenceEngine(): OpenHarmonyInferenceEngine {
    if (!engineInstance) {
        engineInstance = new OpenHarmonyInferenceEngine();
    }
    return engineInstance;
}

